//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-2-14
// @Time:下午4:26
//
/**
 * @brief @file E2EECommon.h
 * @brief @author wujehy
 * @brief E2EE 通用方法集合
 */
#ifndef E2EEMESSAGE_COMMON_H
#define E2EEMESSAGE_COMMON_H

#include <stdint.h>
#include <stddef.h>
#include "signal_protocol.h"
#include <iostream>
#include <exception>
#include "CommonType.h"

namespace GeeJoan
{
    namespace E2EE
    {
        namespace Common
        {
            class CommonException : public std::exception {
            private:
                int errCode = 0;
                std::string errMsg;
            public:
                explicit CommonException(int errcode = 0, std::string errmsg = "")
                {
                    errCode = errcode;
                    errMsg = errmsg;
                }

                int code() const throw()
                {
                    return errCode;
                }

                const std::string &getErrMsg() const
                {
                    return errMsg;
                }

                const char *what() const throw()
                {
                    return "GeeJoan::E2EE::Common::CommonException";
                }
            };

            // crypto 加密公用算法集合
            int common_random_generator(uint8_t *data, size_t len, void *user_data);

            int common_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data);

            int common_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data);

            int common_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data);


            void common_hmac_sha256_cleanup(void *hmac_context, void *user_data);

            int common_sha512_digest_init(void **digest_context, void *user_data);

            int common_sha512_digest_update(void *digest_context,
                                            const uint8_t *data, size_t data_len,
                                            void *user_data);

            int common_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data);

            void common_sha512_digest_cleanup(void *digest_context, void *user_data);

            int common_encrypt(signal_buffer **output,
                               int cipher,
                               const uint8_t *key, size_t key_len,
                               const uint8_t *iv, size_t iv_len,
                               const uint8_t *plaintext, size_t plaintext_len,
                               void *user_data);

            int common_decrypt(signal_buffer **output,
                               int cipher,
                               const uint8_t *key, size_t key_len,
                               const uint8_t *iv, size_t iv_len,
                               const uint8_t *ciphertext, size_t ciphertext_len,
                               void *user_data);

            // 初始化工具
            int common_signal_context_create(signal_context **context, void *user_data);

            void common_setup_crypto_provider(signal_context *context, void *user_data);

            /* 数据保存工具 */
            void setup_common_store_context(signal_protocol_store_context **context, signal_context *global_context);

            /*  会话 操作 方法集合 */
            int common_session_store_load_session(signal_buffer **record, signal_buffer **user_record,
                                                  const signal_protocol_address *address, void *user_data);

            int common_session_store_get_sub_device_sessions(signal_int_list **sessions,
                                                             const char *name, size_t name_len,
                                                             void *user_data);

            int common_session_store_store_session(const signal_protocol_address *address, uint8_t *record,
                                                   size_t record_len, uint8_t *user_record_data, size_t user_record_len,
                                                   void *user_data);

            int common_session_store_contains_session(const signal_protocol_address *address, void *user_data);

            int common_session_store_delete_session(const signal_protocol_address *address, void *user_data);

            int common_session_store_delete_all_sessions(const char *name, size_t name_len, void *user_data);

            void common_session_store_destroy(void *user_data);

            void setup_common_session_store(signal_protocol_store_context *context);


            /* 密钥管理 集合 */
            int common_pre_key_store_load_pre_key(signal_buffer **record, uint32_t pre_key_id, void *user_data);

            int common_pre_key_store_store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len,
                                                   void *user_data);

            int common_pre_key_store_contains_pre_key(uint32_t pre_key_id, void *user_data);

            int common_pre_key_store_remove_pre_key(uint32_t pre_key_id, void *user_data);

            void common_pre_key_store_destroy(void *user_data);

            void setup_common_pre_key_store(signal_protocol_store_context *context);

            /*  预签名 管理集合 */
            int common_signed_pre_key_store_load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id,
                                                                void *user_data);

            int common_signed_pre_key_store_store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record,
                                                                 size_t record_len, void *user_data);

            int common_signed_pre_key_store_contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data);

            int common_signed_pre_key_store_remove_signed_pre_key(uint32_t signed_pre_key_id, void *user_data);

            void common_signed_pre_key_store_destroy(void *user_data);

            void setup_common_signed_pre_key_store(signal_protocol_store_context *context);

            /*  身份密钥管理集合 */
            int common_identity_key_store_get_identity_key_pair(signal_buffer **public_data,
                                                                signal_buffer **private_data,
                                                                void *user_data);

            int common_identity_key_store_get_local_registration_id(void *user_data, uint32_t *registration_id);

            int common_identity_key_store_save_identity(const signal_protocol_address *address, uint8_t *key_data,
                                                        size_t key_len, void *user_data);

            int common_identity_key_store_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data,
                                                              size_t key_len, void *user_data);

            void common_identity_key_store_destroy(void *user_data);

            void setup_common_identity_key_store(signal_protocol_store_context *context,
                                                 signal_context *global_context , ec_key_pair *idk , int32_t localid);

            /*  一次性发件密钥集合 */
            int common_sender_key_store_store_sender_key(const signal_protocol_sender_key_name *sender_key_name,
                                                         uint8_t *record, size_t record_len, uint8_t *user_record_data,
                                                         size_t user_record_len, void *user_data);

            int common_sender_key_store_load_sender_key(signal_buffer **record, signal_buffer **user_record,
                                                        const signal_protocol_sender_key_name *sender_key_name,
                                                        void *user_data);

            void common_sender_key_store_destroy(void *user_data);

            void setup_common_sender_key_store(signal_protocol_store_context *context, signal_context *global_context);

            int64_t jenkins_hash(const char *key, size_t len);

            /* 工具 方法 */
            int64_t jenkins_hash(const char *key, size_t len);


            int serialEcKeyPair(ec_key_pair *keyPair, KeyPairDataType &pairData);

            int deserializationEcKeyPair(KeyPairDataType &pairData, ec_key_pair **keyPair, signal_context *global_context);

            bool serialEcPubKey(ec_public_key *public_key, std::string &serialStr);

            bool serialEcPriKey(ec_private_key *private_key, std::string &serialStr);

            bool
            deserializationEcPubKey(std::string &serialStr, ec_public_key **public_key, signal_context *global_context);

            bool deserializationEcPriKey(std::string &serialStr, ec_private_key **private_key,
                                         signal_context *global_context);

            int serialRatchetKeyPair(ratchet_identity_key_pair *keyPair, KeyPairDataType &pairData);

            int deserializationRatchetKeyPair(KeyPairDataType &pairData, ratchet_identity_key_pair **keyPair,
                                              signal_context *global_context);

            /**
             * @brief 创建一个 公私钥对
             * @param pairData
             * @return 0 --- 成功 , 1 --- 失败
             */
            int creatEcKeyPack(KeyPairDataType &pairData, signal_context *global_context);


            std::string StringToHex(const std::string &data);

            std::string HexToString(const std::string &data);
        }
    }

}


#endif //E2EEMESSAGE_COMMON_H
